/**
 * Grid elements panel - jQuery EasyUI Extension
 * 
 * Copyright (c) 2009-2013 Rime Lee. All rights reserved.
 */
(function($) {
	$.fn.joylist = function(options, param) {
		if (typeof options == 'string') {
			return $.fn.joylist.methods[options](this, param);
		}

		options = options || {};
		return this.each(function() {
			var state = $.data(this, 'joylist');
			if (state) {
				$.extend(state.options, options);
			} else {
				state = {
					options : $.extend({}, $.fn.joylist.defaults, options, {
						loadData : function(data) {
							loadData(this, data);
						}
					})
				};
				$.data(this, 'joylist', state);
			}
			initPanel(this, state);
			if (state.options.data) {
				loadData(this, state.options.data);
			} else {
				$.jsonloader(this, state.options);
			}
		});
	};

	function initPanel(target, state) {
		$(target).addClass('joylist-panel');
		var opts = state.options;
		if (opts.droppable) {
			var accept = null;
			if (opts.acceptName) {
				accept = "div.joylist-item[name='" + opts.acceptName + "']";
			} else {
				accept = "div.joylist-item[name='joylist_item']";
			}
			$(target).droppable({
				accept : accept,
				onDragEnter : function(e, source) {
					$(this).addClass("joylist-dropitem-enter");
				},
				onDragLeave : function(e, source) {
					$(this).removeClass("joylist-dropitem-enter");
				},
				onDrop : function(e, source) {
					$(this).removeClass("joylist-dropitem-enter");
					var d = $.data(source, "joylist-item");
					appendItem(this, d, true);
				}
			});
		}
	}

	function getPanel(target) {
		return $(target);
	}

	/**
	 * load data, the old items will be removed.
	 */
	function loadData(target, data) {
		var opts = $.data(target, 'joylist').options;
		$.data(target, 'joylist').data = data;
		var panel = getPanel(target);
		panel.empty();
		for ( var i = 0; i < data.length; i++) {
			if (opts.filter && (opts.filter.call(target, data[i]) == false)) {
				continue;
			}
			createItem(target, panel, opts, data[i]);
		}
	}

	function createItem(target, panel, opts, itemData) {
		var item = $('<div class="joylist-item"></div>').appendTo(panel);
		if (opts.name) {
			item.attr("name", opts.name);
		} else {
			item.attr("name", "joylist_item");
		}
		$.data(item[0], "joylist-item", $.extend({}, itemData, {
			target : item[0]
		}));
		formatter(item, itemData, opts);
		bindEvent(target, opts, item);
		return item;
	}

	function formatter(item, itemData, opts) {
		if (itemData.iconCls) {
			$("<div></div>").appendTo(item).addClass("joylist-item-icon")
					.addClass(itemData.iconCls);
		}
		if (opts.removable) {
			$("<div></div>").appendTo(item).addClass("joylist-item-remove");
		}
		if (itemData.name) {
			$("<div></div>").appendTo(item).addClass("joylist-item-name").html(
					itemData.name);
		}
		if (itemData.brief) {
			$("<div></div>").appendTo(item).addClass("joylist-item-brief")
					.html(itemData.brief);
		}
	}

	function bindEvent(target, opts, item) {
		if (opts.draggable) {
			item.hover(function() {
				$(this).addClass('joylist-dragitem-hover');
			}, function() {
				$(this).removeClass('joylist-dragitem-hover');
			});
			item.draggable({
				revert : true,
				proxy : function(source) {
					var w = $(source).width();
					return $(source).clone().width(w).appendTo('body');
				},
				onBeforeDrag : function(e) {

				},
				onStartDrag : function(e) {
					$(this).draggable('proxy').css('z-index', 999);
				}
			});
		} else {
			item.hover(function() {
				$(this).addClass("joylist-item-hover");
				if (opts.removable) {
					var remove = $("div.joylist-item-remove", this).addClass(
							"joylist-item-remove-icon").addClass();
					remove.bind("click", {
						list : target,
						item : this
					}, function(e) {
						$(this).unbind();
						removeItem(e.data.list, e.data.item, true);
					});
				}
			}, function() {
				$(this).removeClass("joylist-item-hover");
				if (opts.removable) {
					$("div.joylist-item-remove", this).removeClass(
							"joylist-item-remove-icon").unbind();
				}
			});
		}
	}

	function appendItem(target, itemData, fireEvent) {
		var opts = $.data(target, 'joylist').options;
		if (opts.filter && (opts.filter.call(target, itemData) == false)) {
			return false;
		}
		var data = $.data(target, 'joylist').data;
		for ( var i = 0; i < data.length; i++) {
			if (itemData.id == data[i].id) {
				return false;
			}
		}
		if (fireEvent && opts.onAppend
				&& (opts.onAppend.call(target, itemData) == false)) {
			return false;
		}
		data.push(itemData);
		var panel = getPanel(target);
		createItem(target, panel, opts, itemData);
	}

	function removeItem(target, itemEl, fireEvent) {
		var opts = $.data(target, 'joylist').options;
		var itemData = $.data(itemEl, 'joylist-item');
		if (fireEvent && opts.onRemove
				&& (opts.onRemove.call(target, itemData) == false)) {
			return false;
		}
		var data = $.data(target, 'joylist').data;
		for ( var i = 0; i < data.length; i++) {
			if (itemData.id == data[i].id) {
				data.splice(i, 1);
				break;
			}
		}
		$.removeData(itemEl, "joylist-item");
		$(itemEl).unbind();
		$(itemEl).remove();
	}

	$.fn.joylist.methods = {
		options : function(jq) {
			return $.data(jq[0], 'joylist').options;
		},
		getData : function(jq) {
			return $.data(jq[0], 'joylist').data;
		},
		load : function(jq, data) {
			return jq.each(function() {
				loadData(this, data);
			});
		},
		reload : function(jq, param) {
			return jq.each(function() {
				var opts = $.data(jq[0], 'joylist').options;
				if (param) {
					opts.queryParams = param;
				}
				$.jsonloader(this, opts);
			});
		},
		/**
		 * append grid item, the param contains following properties:
		 * id,name,brief,iconCls,attributes
		 */
		appendItem : function(jq, param) {
			return jq.each(function() {
				appendItem(this, param, false);
			});
		},
		removeItem : function(jq, itemEl) {
			return jq.each(function() {
				removeItem(this, itemEl, false);
			});
		}
	};

	$.fn.joylist.defaults = $.extend({}, $.jsonloader.defaults, {
		name : null,
		draggable : false,
		droppable : false,
		removable : false,
		acceptName : null,
		unique : true,
		data : null,
		filter : function(item) {
			return true;
		},
		onAppend : function(obj) {
			return true;
		},
		onRemove : function(obj) {
			return true;
		}
	});

	var cssloaded = false;
	if (window.jQuery) {
		jQuery(function() {
			if (!cssloaded) {
				easyloader.load('extends/joylist.css', function() {
					cssloaded = true;
				});
			}
		});
	}
})(jQuery);